import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 权重轮询调度
 *
 * @author Andy
 */
public class WeightedRound {

    private List<Server> serverList; // 服务器集合

    public static void main(String[] args) {
        WeightedRound obj = new WeightedRound();
        obj.init();

        Map<String, Integer> countResult = new HashMap<String, Integer>();
        for (int i = 0; i < 1000; i++) {
            Server s = obj.getBestServer();
            obj.outInfo();
            obj.oute();
            System.out.println("=============");
            String log = "ip:" + s.ip + ";weight:" + s.weight;
            if (countResult.containsKey(log)) {
                countResult.put(log, countResult.get(log) + 1);
            } else {
                countResult.put(log, 1);
            }
        }
        for (Entry<String, Integer> map : countResult.entrySet()) {
            System.out.println("服务器 " + map.getKey() + " 请求次数： " + map.getValue());
        }
    }

    public void setServerList(List<Server> serverList) {
        this.serverList = serverList;
    }

    public Server getBestServer() {
        Server server = null;
        Server best = null;
        int total = 0;
        for (int i = 0, len = serverList.size(); i < len; i++) {
            // 当前服务器对象
            server = serverList.get(i);

            // 每次获取请求按权重提升当前权重
            server.currentWeight += server.effectiveWeight;
            // 为保持平衡，将所有提升的权重累加，在选出结果后扣除该权重
            total += server.effectiveWeight;

            // 有效权重自适应
            if (server.effectiveWeight < server.weight) {
                server.effectiveWeight++;
            }

            // 选出当前权重因子最大的作为最终结果
            if (best == null || server.currentWeight > best.currentWeight) {
                best = server;
            }
        }

        if (best == null) {
            return null;
        }

        // 选出的结果后从扣除本次循环所有负载累加的权重，把这个负载推到队列的最后方
        best.currentWeight -= total;
        return best;
    }

    public void init() {
        Server s1 = new Server("192.168.0.100", 3);// 3
        Server s2 = new Server("192.168.0.101", 2);// 2
        Server s3 = new Server("192.168.0.102", 6);// 6
        Server s4 = new Server("192.168.0.103", 4);// 4
        Server s5 = new Server("192.168.0.104", 1);// 1
        Server s6 = new Server("192.168.0.105", 0);// 0
        Server s7 = new Server("192.168.0.106", 0);// 0
        Server s8 = new Server("192.168.0.107", 0);// 0
        Server s9 = new Server("192.168.0.108", 0);// 0
        List<Server> sl = new ArrayList<>();
        sl.add(s1);
        sl.add(s2);
        sl.add(s3);
        sl.add(s4);
        sl.add(s5);
        sl.add(s6);
        sl.add(s7);
        sl.add(s8);
        sl.add(s9);

        setServerList(sl);
    }

    private void outInfo() {
        StringBuilder stringBuilder = new StringBuilder();
        serverList.forEach(server -> {
            stringBuilder.append(server.currentWeight).append(",");
        });
        System.out.println(stringBuilder.toString());
    }

    private void oute() {
        StringBuilder stringBuilder = new StringBuilder();
        serverList.forEach(server -> {
            stringBuilder.append(server.effectiveWeight).append(",");
        });
        System.out.println(stringBuilder.toString());
    }
}

/**
 * 运行结果
 * 服务器 ip:192.168.0.104;weight:1 请求次数： 62
 * 服务器 ip:192.168.0.101;weight:2 请求次数： 125
 * 服务器 ip:192.168.0.102;weight:6 请求次数： 375
 * 服务器 ip:192.168.0.100;weight:3 请求次数： 188
 * 服务器 ip:192.168.0.103;weight:4 请求次数： 250
 */
